package taxexporter.wizards;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.widgets.Button;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;

import taxexporter.ui.pages.NewPagePage;
import taxexporter.util.Consts;
import taxexporter.util.Util;

/**
 * New Page Wizard
 * 
 * @author sunny
 *
 */
public class NewPageWizard extends Wizard implements INewWizard {
	private ISelection selection;
	private NewPagePage newPagePage;
	public boolean isOk;

	public NewPageWizard() {
		super();
		this.setWindowTitle("New Tax Page");
		isOk = false;
	}

	@Override
	public void addPages() {
		newPagePage = new NewPagePage(selection);
		newPagePage.setCaller(this);
		this.addPage(newPagePage);
	}

	private String getCurrentPageType() {
		List<Button> buttons = newPagePage.getButtons();
		for (Button button : buttons) {
			if (button.getSelection()) {
				return button.getText();
			}
		}
		return "";
	}

	private boolean findModule(String moduleUrl, String moduleContent) {
		Pattern pat = Pattern.compile("desc\\s*:\\s*'.*?'\\s*,\\s*url\\s*:\\s*'(.*?)'");
		Matcher mat = pat.matcher(moduleContent);
		while (mat.find()) {
			String url = mat.group(1);
			if (url.equals(moduleUrl))
				return true;
		}
		return false;
	}

	public void doFinish(String controllerName, String htmlPath, String url, String projectPath, String currentPageType,
			String desc, IProgressMonitor monitor) {
		monitor.beginTask("Create pages...", 3);
		final String retHtmlPath = "/src/main/webapp/WEB-INF/pages" + htmlPath + ".html";
		final String retJsPath = "/src/main/webapp/js/app" + htmlPath + ".js";
		String htmlFullPath = projectPath + retHtmlPath;
		String jsPath = projectPath + retJsPath;
		File f = new File(htmlFullPath);
		if (f.exists()) {
			MessageDialog.openError(getShell(), "Error", "HTML file (same name) is exists!");
			monitor.worked(1);
			return;
		}

		f = new File(jsPath);
		if (f.exists()) {
			MessageDialog.openError(getShell(), "Error", "Js file (same name) is exists!");
			monitor.worked(1);
			return;
		}

		String modulesContent;
		String moduleJsPath = projectPath + "/src/main/webapp/js/app/modules.js";
		try {
			modulesContent = Util.file2Str(moduleJsPath, Consts.DEFAULT_ENCODE);
			if (findModule(url, modulesContent)) {
				getShell().getDisplay().asyncExec(new Runnable() {

					@Override
					public void run() {
						MessageDialog.openError(getShell(), "Error", "URL is exists");
					}
				});
				monitor.worked(1);
				return;
			}
		} catch (IOException e1) {
			e1.printStackTrace();
			return;
		}
		monitor.worked(1);
		try {
			String pageContent = Util.file2Str(projectPath + "/plugins/templates/" + currentPageType + ".html",
					Consts.DEFAULT_ENCODE);
			pageContent = pageContent.replaceAll("##controllerName##", controllerName);
			// Util.str2File(htmlFullPath, Consts.DEFAULT_ENCODE, pageContent);
			Util.createFile(currentProject, retHtmlPath, pageContent, true);
			String jsContent = Util.file2Str(projectPath + "/plugins/templates/" + currentPageType + ".js",
					Consts.DEFAULT_ENCODE);
			jsContent = jsContent.replaceAll("##controllerName##", controllerName);
			// Util.str2File(jsPath, Consts.DEFAULT_ENCODE, jsContent);
			Util.createFile(currentProject, retJsPath, jsContent, true);
		} catch (IOException e) {
			e.printStackTrace();
			monitor.worked(1);
			return;
		} catch (CoreException e) {
			e.printStackTrace();
		}
		monitor.worked(1);
		try {
			String jsStub = Util.file2Str(projectPath + "/plugins/templates/" + currentPageType + ".txt",
					Consts.DEFAULT_ENCODE);
			jsStub = jsStub.replaceAll("##url##", url).replaceAll("##desc##", desc)
					.replaceAll("##name##", controllerName).replaceAll("##path##", "app" + htmlPath);
			jsStub = jsStub + "\n					// do not delete this line;";
			modulesContent = modulesContent.replace("// do not delete this line;", ", \n" + jsStub);
			Util.str2File(moduleJsPath, Consts.DEFAULT_ENCODE, modulesContent);
		} catch (IOException e) {
			e.printStackTrace();
			monitor.worked(1);
			return;
		}
		monitor.worked(1);
		monitor.setTaskName("Refresh Project");
		getShell().getDisplay().asyncExec(new Runnable() {

			@Override
			public void run() {
				Util.openSource(retHtmlPath);
				Util.openSource(retJsPath);
			}
		});
		monitor.worked(1);
	}

	private IProject currentProject;

	@Override
	public boolean performFinish() {
		currentProject = Util.getCurrentProject();
		final String controllerName = newPagePage.getPageControllerText().getText();
		final String htmlPath = newPagePage.getPagePathText().getText();
		final String url = newPagePage.getPageUrlText().getText();
		final String projectPath = currentProject.getLocation().toFile().getAbsolutePath();
		final String currentPageType = getCurrentPageType();
		final String desc = newPagePage.getPageDescText().getText();
		IRunnableWithProgress op = new IRunnableWithProgress() {

			@Override
			public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
				doFinish(controllerName, htmlPath, url, projectPath, currentPageType, desc, monitor);
			}
		};

		try {
			getContainer().run(true, false, op);
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		return true;
	}

	@Override
	public void init(IWorkbench workbench, IStructuredSelection selection) {
		this.selection = selection;
	}

	@Override
	public boolean canFinish() {
		return isOk;
	}
}
